var canvas;
var gl;
var projection_matrix = mat4.create();
var modelview_matrix = mat4.create();


function DrawTriangle()
{
	var context = canvas.getContext('2d');

	var width = 125;  // Triangle Width
	var height = 105; // Triangle Height
	var padding = 20;

	// Draw a path
	context.beginPath();
	context.moveTo(padding + width/2, padding);        // Top Corner
	context.lineTo(padding + width, height + padding); // Bottom Right
	context.lineTo(padding, height + padding);         // Bottom Left
	context.closePath();

	// Create fill gradient
	gradient = context.createLinearGradient(0,padding,0,padding+height);
	gradient.addColorStop(0.5, "transparent");
	gradient.addColorStop(0.5, "#dcaa09"); 
	gradient.addColorStop(1, "#faf100");


	// Add a shadow around the object
	context.shadowBlur = 10;
	context.shadowColor = "black";

	// Fill the path
	//context.fillStyle = "#ffc821";
	context.fillStyle = gradient;
	context.fill();

	// Stroke the inner outline
	context.lineWidth = 5;
	context.lineJoin = "round";	
	context.strokeStyle = "#333";
	context.stroke();
}


function InitWebGL()
{
	if (!window.WebGLRenderingContext) 
	{
		alert("Your browser doesn't appear to support WebGL");
	}

	try 
	{
		gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
		gl.viewportWidth = canvas.width;
		gl.viewportHeight = canvas.height;
	} 
	catch(e) 
	{
	}
	
	if (!gl) 
	{
		alert("Your browser doesn't appear to support WebGL");
	}
	else
	{
		gl.enable(gl.DEPTH_TEST);                               // Enable depth testing  
		gl.depthFunc(gl.LEQUAL);                                // Near things obscure far things  
	}
}

// Read and compile shader
function GetShader(id) 
{
	var shaderScript = document.getElementById(id);
	if (!shaderScript) 
	{
		return null;
	}

	var str = "";
	var k = shaderScript.firstChild;
	while (k) 
	{
		if (k.nodeType == 3) 
		{
		  str += k.textContent;
		}
		k = k.nextSibling;
	}
	
	var shader;
	if (shaderScript.type == "x-shader/x-fragment") 
	{
		shader = gl.createShader(gl.FRAGMENT_SHADER);
	} 
	else if (shaderScript.type == "x-shader/x-vertex") 
	{
		shader = gl.createShader(gl.VERTEX_SHADER);
	} 
	else 
	{
		return null;
	}
	
	gl.shaderSource(shader, str);
	gl.compileShader(shader);

	if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) 
	{
		alert(gl.getShaderInfoLog(shader));
		return null;
	}
	
	return shader;
}

// Init shader and get attributes and uniform hooks
function InitShaders()
{
	// Get compiled shaders and attach them to a program
	var fshader = GetShader("fshader");
	var vshader = GetShader("vshader");

	shaderProgram = gl.createProgram();
	gl.attachShader(shaderProgram, fshader);
	gl.attachShader(shaderProgram, vshader);
	gl.linkProgram(shaderProgram);
	gl.useProgram(shaderProgram);

	if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) 
	{
		alert("Could not initialise shaders");
	}
	
	// Get vertex attributes hooks
	shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram,		"a_vtx_position");
	gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
/*
	shaderProgram.vertexNormalAttribute = gl.getAttribLocation(shaderProgram,		"a_vtx_normal");
	gl.enableVertexAttribArray(shaderProgram.vertexNormalAttribute);

	shaderProgram.vertexColorAttribute = gl.getAttribLocation(shaderProgram,		"a_vtx_color");
	gl.enableVertexAttribArray(shaderProgram.vertexColorAttribute);

	shaderProgram.textureCoordAttribute = gl.getAttribLocation(shaderProgram,		"a_vtx_texcoord");
	gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute);
	*/
	
	// Get matrix hooks
	shaderProgram.pMatrixUniform = gl.getUniformLocation(shaderProgram,		"u_projection_mat");	
	shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram,	"u_modelview_mat");
}

function SetMatrixUniforms()
{
	gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, false, projection_matrix);
	gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform, false, modelview_matrix);
}

var triangleVertexPositionBuffer;
var squareVertexPositionBuffer;
function InitScene()
{
	// Create & attach vertex buffers
	
	// Triangle
	triangleVertexPositionBuffer = gl.createBuffer();
	gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexPositionBuffer);
	var vertices = [
		 0.0,  1.0,  0.0,
		-1.0, -1.0,  0.0,
		 1.0, -1.0,  0.0
	];
	gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
	triangleVertexPositionBuffer.itemSize = 3;
	triangleVertexPositionBuffer.numItems = 3;

	// Square
	squareVertexPositionBuffer = gl.createBuffer();
	gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer);
	vertices = [
		 1.0,  1.0,  0.0,
		-1.0,  1.0,  0.0,
		 1.0, -1.0,  0.0,
		-1.0, -1.0,  0.0
	];
	gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
	squareVertexPositionBuffer.itemSize = 3;
	squareVertexPositionBuffer.numItems = 4;
}

function UpdateScene()
{
	// Update display
	gl.clearColor(0.0, 1.0, 1.0, 1.0);
	gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT);      // Clear the color as well as the depth buffer.

	// Set projection/model view matrix
	mat4.perspective(45, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0, projection_matrix);
	mat4.identity(modelview_matrix);
	
	// Draw triangle
	mat4.translate(modelview_matrix, [-1.5, 0.0, -7.0]);
	gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexPositionBuffer);
	gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, triangleVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
	SetMatrixUniforms();
	gl.drawArrays(gl.TRIANGLES, 0, triangleVertexPositionBuffer.numItems);	
	
	// Draw square
	mat4.translate(modelview_matrix, [3.0, 0.0, 0.0]);
	gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer);
	gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, squareVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
	SetMatrixUniforms();
	gl.drawArrays(gl.TRIANGLE_STRIP, 0, squareVertexPositionBuffer.numItems);
}


function main()
{
	canvas = document.getElementById('tutorial');
	document.write("<br>TEST");
	
	// 2d example
	//DrawTriangle();
	
	// 3d example
	InitWebGL();
	InitShaders();

	// Init & update scene
	InitScene();
	UpdateScene();
	//setInterval(UpdateScene, 10);
}
